#ifndef ARMORY_H
#define ARMORY_H

#include "item.h"

/*
To Do: make items read from text files, only effects (constant and on hit/on parrying) and basic characteristics should be hardcoded.
*/


template< typename T >
Armor * armorInstance()
{
	return reinterpret_cast< Armor * >( new T() );
}
#define DECLARE_ARMOR template< typename T > friend T * instance< T >(); template< typename T > friend Armor * armorInstance< T >();
std::map< std::string, Armor * ( * )() > & getArmorTypes();
#define DECLARE_ARMOR_TYPE( a ) \
	inline static int a##AddToTypeslist() { getArmorTypes()[ #a ] = armorInstance< a >; return 1; }; static int a##AddToType = a##AddToTypeslist();

class Armor : public Item
{
public:
	DECLARE_INSTANCE;
	DECLARE_ARMOR;
	Armor( int x, int y, std::string const & name = "armor", char symbol = '[' );
	Armor( const armor_t &, int x, int y ); // to do: implement this as a function (polymorphic?)
    int getProtection() const;
	int getHealth() const;
	int protect( int force/*, int type*/ );
protected:
	Armor();


	int protection;
	int health;
};

DECLARE_ARMOR_TYPE( Armor );


template< typename T >
Weapon * weaponInstance()
{
	return reinterpret_cast< Weapon * >( new T() );
}
#define DECLARE_WEAPON template< typename T > friend T * instance< T >(); template< typename T > friend Weapon * weaponInstance< T >();
std::map< std::string, Weapon * ( * )() > & getWeaponTypes();
#define DECLARE_WEAPON_TYPE( w ) \
	inline static int w##AddToTypeslist() { getWeaponTypes()[ #w ] = weaponInstance< w >; return 1; }; static int w##AddToType = w##AddToTypeslist();

class Weapon : public Item
{
public:
	DECLARE_WEAPON;
	Weapon( int x, int y, std::string const & name = "weapon", char symbol = '/' );
	Weapon( const weapon_t &, int x, int y );
	Weapon & operator = ( const weapon_t & );
	int getDamage() const;
	virtual int hit( Monster * );
	MapObject * fire( MapObject * target );
	bool isFirearm() const;
protected:
	Weapon();


	int damage;
	int shotDamage;
	bool firearm;
};

DECLARE_WEAPON_TYPE( Weapon );

class LifeStealer : public Weapon
{
public:
	DECLARE_WEAPON;
	virtual int hit( Monster * ) override;
protected:
	LifeStealer(); // should be added with a macro

	int uses;
};

DECLARE_WEAPON_TYPE( LifeStealer );

#endif